# -*- coding: utf-8 -*-
# @author: HRUN

import os
import json
from datetime import datetime
from typing import Dict, List, Optional, Any
from jinja2 import Template, Environment, FileSystemLoader
import base64
import io
import matplotlib.pyplot as plt
import matplotlib
matplotlib.use('Agg')  # 使用非交互式后端
import seaborn as sns
import numpy as np
from dataclasses import dataclass

# 设置中文字体
plt.rcParams['font.sans-serif'] = ['SimHei', 'DejaVu Sans']
plt.rcParams['axes.unicode_minus'] = False


@dataclass
class ReportTemplate:
    """报告模板"""
    name: str
    template_type: str  # 'summary', 'detailed', 'comparison', 'trend'
    description: str
    template_content: str
    css_styles: str = ""
    chart_configs: Dict = None
    
    def __post_init__(self):
        if self.chart_configs is None:
            self.chart_configs = {}


class PerformanceReportGenerator:
    """性能报告生成器"""
    
    def __init__(self):
        self.templates = {}
        self._init_default_templates()
        
    def _init_default_templates(self):
        """初始化默认模板"""
        
        # 摘要报告模板
        summary_template = ReportTemplate(
            name="摘要报告",
            template_type="summary",
            description="简洁的性能测试摘要报告",
            template_content=self._get_summary_template(),
            css_styles=self._get_common_css(),
            chart_configs={
                'tps_chart': {'type': 'line', 'title': 'TPS趋势'},
                'response_time_chart': {'type': 'line', 'title': '响应时间趋势'},
                'error_rate_chart': {'type': 'bar', 'title': '错误率分布'}
            }
        )
        
        # 详细报告模板
        detailed_template = ReportTemplate(
            name="详细报告",
            template_type="detailed", 
            description="详细的性能测试分析报告",
            template_content=self._get_detailed_template(),
            css_styles=self._get_common_css(),
            chart_configs={
                'performance_overview': {'type': 'multi_metric', 'title': '性能概览'},
                'response_time_distribution': {'type': 'histogram', 'title': '响应时间分布'},
                'tps_timeline': {'type': 'line', 'title': 'TPS时间线'},
                'error_analysis': {'type': 'pie', 'title': '错误类型分析'},
                'system_resources': {'type': 'multi_line', 'title': '系统资源使用'}
            }
        )
        
        # 对比报告模板
        comparison_template = ReportTemplate(
            name="对比报告",
            template_type="comparison",
            description="多任务性能对比报告",
            template_content=self._get_comparison_template(),
            css_styles=self._get_common_css(),
            chart_configs={
                'performance_comparison': {'type': 'bar_comparison', 'title': '性能指标对比'},
                'trend_comparison': {'type': 'multi_line', 'title': '趋势对比'},
                'ranking_chart': {'type': 'radar', 'title': '综合排名'}
            }
        )
        
        self.templates['summary'] = summary_template
        self.templates['detailed'] = detailed_template
        self.templates['comparison'] = comparison_template
    
    def _get_common_css(self) -> str:
        """通用CSS样式"""
        return """
        <style>
        body {
            font-family: 'Microsoft YaHei', Arial, sans-serif;
            line-height: 1.6;
            margin: 0;
            padding: 20px;
            background-color: #f5f5f5;
        }
        
        .report-container {
            max-width: 1200px;
            margin: 0 auto;
            background-color: white;
            padding: 30px;
            border-radius: 8px;
            box-shadow: 0 2px 10px rgba(0,0,0,0.1);
        }
        
        .report-header {
            text-align: center;
            border-bottom: 2px solid #3498db;
            padding-bottom: 20px;
            margin-bottom: 30px;
        }
        
        .report-title {
            color: #2c3e50;
            font-size: 28px;
            margin-bottom: 10px;
        }
        
        .report-subtitle {
            color: #7f8c8d;
            font-size: 16px;
        }
        
        .metrics-grid {
            display: grid;
            grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
            gap: 20px;
            margin-bottom: 30px;
        }
        
        .metric-card {
            background-color: #f8f9fa;
            padding: 20px;
            border-radius: 6px;
            border-left: 4px solid #3498db;
        }
        
        .metric-title {
            font-size: 14px;
            color: #7f8c8d;
            margin-bottom: 8px;
        }
        
        .metric-value {
            font-size: 24px;
            font-weight: bold;
            color: #2c3e50;
        }
        
        .metric-unit {
            font-size: 14px;
            color: #95a5a6;
        }
        
        .section {
            margin-bottom: 40px;
        }
        
        .section-title {
            font-size: 20px;
            color: #2c3e50;
            border-bottom: 1px solid #ecf0f1;
            padding-bottom: 10px;
            margin-bottom: 20px;
        }
        
        .chart-container {
            text-align: center;
            margin: 20px 0;
        }
        
        .chart-image {
            max-width: 100%;
            height: auto;
            border-radius: 4px;
            box-shadow: 0 2px 8px rgba(0,0,0,0.1);
        }
        
        .table {
            width: 100%;
            border-collapse: collapse;
            margin-top: 20px;
        }
        
        .table th,
        .table td {
            border: 1px solid #dee2e6;
            padding: 12px;
            text-align: left;
        }
        
        .table th {
            background-color: #f8f9fa;
            font-weight: bold;
            color: #495057;
        }
        
        .table tbody tr:nth-child(even) {
            background-color: #f8f9fa;
        }
        
        .alert {
            padding: 15px;
            margin-bottom: 20px;
            border-radius: 4px;
        }
        
        .alert-success {
            background-color: #d4edda;
            border-color: #c3e6cb;
            color: #155724;
        }
        
        .alert-warning {
            background-color: #fff3cd;
            border-color: #ffeaa7;
            color: #856404;
        }
        
        .alert-danger {
            background-color: #f8d7da;
            border-color: #f5c6cb;
            color: #721c24;
        }
        
        .recommendations {
            background-color: #e8f4fd;
            border-left: 4px solid #17a2b8;
            padding: 20px;
            margin-top: 20px;
        }
        
        .recommendations h4 {
            color: #0c5460;
            margin-bottom: 15px;
        }
        
        .recommendations ul {
            margin: 0;
            padding-left: 20px;
        }
        
        .recommendations li {
            margin-bottom: 8px;
            color: #0c5460;
        }
        
        .footer {
            text-align: center;
            color: #7f8c8d;
            font-size: 12px;
            margin-top: 40px;
            padding-top: 20px;
            border-top: 1px solid #ecf0f1;
        }
        </style>
        """
    
    def _get_summary_template(self) -> str:
        """摘要报告模板"""
        return """
        <!DOCTYPE html>
        <html lang="zh-CN">
        <head>
            <meta charset="UTF-8">
            <meta name="viewport" content="width=device-width, initial-scale=1.0">
            <title>{{ report_title }}</title>
            {{ css_styles|safe }}
        </head>
        <body>
            <div class="report-container">
                <div class="report-header">
                    <h1 class="report-title">{{ report_title }}</h1>
                    <p class="report-subtitle">{{ task_name }} - {{ test_date }}</p>
                </div>
                
                <div class="metrics-grid">
                    <div class="metric-card">
                        <div class="metric-title">平均TPS</div>
                        <div class="metric-value">{{ metrics.avg_tps|round(2) }} <span class="metric-unit">req/s</span></div>
                    </div>
                    <div class="metric-card">
                        <div class="metric-title">平均响应时间</div>
                        <div class="metric-value">{{ metrics.avg_response_time|round(2) }} <span class="metric-unit">ms</span></div>
                    </div>
                    <div class="metric-card">
                        <div class="metric-title">错误率</div>
                        <div class="metric-value">{{ metrics.error_rate|round(2) }} <span class="metric-unit">%</span></div>
                    </div>
                    <div class="metric-card">
                        <div class="metric-title">总请求数</div>
                        <div class="metric-value">{{ metrics.total_requests|int }}</div>
                    </div>
                </div>
                
                {% if performance_grade %}
                <div class="section">
                    <h2 class="section-title">性能评级</h2>
                    {% if performance_grade == 'A' %}
                    <div class="alert alert-success">
                        <strong>性能评级: {{ performance_grade }}</strong> - 性能表现优秀！
                    </div>
                    {% elif performance_grade == 'B' %}
                    <div class="alert alert-success">
                        <strong>性能评级: {{ performance_grade }}</strong> - 性能表现良好
                    </div>
                    {% elif performance_grade == 'C' %}
                    <div class="alert alert-warning">
                        <strong>性能评级: {{ performance_grade }}</strong> - 性能一般，有改进空间
                    </div>
                    {% else %}
                    <div class="alert alert-danger">
                        <strong>性能评级: {{ performance_grade }}</strong> - 性能需要优化
                    </div>
                    {% endif %}
                </div>
                {% endif %}
                
                {% if charts %}
                <div class="section">
                    <h2 class="section-title">性能趋势</h2>
                    {% for chart_name, chart_data in charts.items() %}
                    <div class="chart-container">
                        <img src="data:image/png;base64,{{ chart_data }}" alt="{{ chart_name }}" class="chart-image">
                    </div>
                    {% endfor %}
                </div>
                {% endif %}
                
                {% if recommendations %}
                <div class="recommendations">
                    <h4>优化建议</h4>
                    <ul>
                    {% for recommendation in recommendations %}
                        <li>{{ recommendation }}</li>
                    {% endfor %}
                    </ul>
                </div>
                {% endif %}
                
                <div class="footer">
                    <p>报告生成时间: {{ generation_time }}</p>
                    <p>由 HRUN 性能测试平台自动生成</p>
                </div>
            </div>
        </body>
        </html>
        """
    
    def _get_detailed_template(self) -> str:
        """详细报告模板"""
        return """
        <!DOCTYPE html>
        <html lang="zh-CN">
        <head>
            <meta charset="UTF-8">
            <meta name="viewport" content="width=device-width, initial-scale=1.0">
            <title>{{ report_title }}</title>
            {{ css_styles|safe }}
        </head>
        <body>
            <div class="report-container">
                <div class="report-header">
                    <h1 class="report-title">{{ report_title }}</h1>
                    <p class="report-subtitle">{{ task_name }} - {{ test_date }}</p>
                </div>
                
                <!-- 性能概览 -->
                <div class="section">
                    <h2 class="section-title">性能概览</h2>
                    <div class="metrics-grid">
                        <div class="metric-card">
                            <div class="metric-title">平均TPS</div>
                            <div class="metric-value">{{ metrics.avg_tps|round(2) }} <span class="metric-unit">req/s</span></div>
                        </div>
                        <div class="metric-card">
                            <div class="metric-title">最大TPS</div>
                            <div class="metric-value">{{ metrics.max_tps|round(2) }} <span class="metric-unit">req/s</span></div>
                        </div>
                        <div class="metric-card">
                            <div class="metric-title">平均响应时间</div>
                            <div class="metric-value">{{ metrics.avg_response_time|round(2) }} <span class="metric-unit">ms</span></div>
                        </div>
                        <div class="metric-card">
                            <div class="metric-title">P95响应时间</div>
                            <div class="metric-value">{{ metrics.p95_response_time|round(2) }} <span class="metric-unit">ms</span></div>
                        </div>
                        <div class="metric-card">
                            <div class="metric-title">P99响应时间</div>
                            <div class="metric-value">{{ metrics.p99_response_time|round(2) }} <span class="metric-unit">ms</span></div>
                        </div>
                        <div class="metric-card">
                            <div class="metric-title">错误率</div>
                            <div class="metric-value">{{ metrics.error_rate|round(2) }} <span class="metric-unit">%</span></div>
                        </div>
                    </div>
                </div>
                
                <!-- 测试配置 -->
                <div class="section">
                    <h2 class="section-title">测试配置</h2>
                    <table class="table">
                        <tr><th>测试任务</th><td>{{ task_name }}</td></tr>
                        <tr><th>测试环境</th><td>{{ test_config.environment or '默认环境' }}</td></tr>
                        <tr><th>并发用户数</th><td>{{ test_config.concurrent_users or 'N/A' }}</td></tr>
                        <tr><th>测试持续时间</th><td>{{ test_config.duration or 'N/A' }} 秒</td></tr>
                        <tr><th>分布式模式</th><td>{{ test_config.distributed_mode or '单机模式' }}</td></tr>
                    </table>
                </div>
                
                <!-- 性能图表 -->
                {% if charts %}
                <div class="section">
                    <h2 class="section-title">性能图表</h2>
                    {% for chart_name, chart_data in charts.items() %}
                    <div class="chart-container">
                        <h3>{{ chart_configs[chart_name].title if chart_configs and chart_name in chart_configs else chart_name }}</h3>
                        <img src="data:image/png;base64,{{ chart_data }}" alt="{{ chart_name }}" class="chart-image">
                    </div>
                    {% endfor %}
                </div>
                {% endif %}
                
                <!-- 错误分析 -->
                {% if error_analysis and error_analysis.total_errors > 0 %}
                <div class="section">
                    <h2 class="section-title">错误分析</h2>
                    <p>总错误数: {{ error_analysis.total_errors }}</p>
                    <p>错误类型: {{ error_analysis.error_types_count }}</p>
                    
                    {% if error_analysis.top_errors %}
                    <h4>主要错误类型</h4>
                    <table class="table">
                        <thead>
                            <tr>
                                <th>错误类型</th>
                                <th>错误次数</th>
                                <th>占比</th>
                            </tr>
                        </thead>
                        <tbody>
                            {% for error in error_analysis.top_errors %}
                            <tr>
                                <td>{{ error.error_type }}</td>
                                <td>{{ error.count }}</td>
                                <td>{{ error.percentage|round(2) }}%</td>
                            </tr>
                            {% endfor %}
                        </tbody>
                    </table>
                    {% endif %}
                </div>
                {% endif %}
                
                <!-- 瓶颈分析 -->
                {% if bottleneck_analysis and bottleneck_analysis.bottlenecks %}
                <div class="section">
                    <h2 class="section-title">瓶颈分析</h2>
                    {% for bottleneck in bottleneck_analysis.bottlenecks %}
                    <div class="alert {% if bottleneck.severity == 'high' %}alert-danger{% elif bottleneck.severity == 'medium' %}alert-warning{% else %}alert-success{% endif %}">
                        <strong>{{ bottleneck.severity.upper() }}</strong>: {{ bottleneck.description }}
                    </div>
                    {% endfor %}
                </div>
                {% endif %}
                
                <!-- 优化建议 -->
                {% if recommendations %}
                <div class="recommendations">
                    <h4>优化建议</h4>
                    <ul>
                    {% for recommendation in recommendations %}
                        <li>{{ recommendation }}</li>
                    {% endfor %}
                    </ul>
                </div>
                {% endif %}
                
                <div class="footer">
                    <p>报告生成时间: {{ generation_time }}</p>
                    <p>由 HRUN 性能测试平台自动生成</p>
                </div>
            </div>
        </body>
        </html>
        """
    
    def _get_comparison_template(self) -> str:
        """对比报告模板"""
        return """
        <!DOCTYPE html>
        <html lang="zh-CN">
        <head>
            <meta charset="UTF-8">
            <meta name="viewport" content="width=device-width, initial-scale=1.0">
            <title>{{ report_title }}</title>
            {{ css_styles|safe }}
        </head>
        <body>
            <div class="report-container">
                <div class="report-header">
                    <h1 class="report-title">{{ report_title }}</h1>
                    <p class="report-subtitle">性能对比分析报告 - {{ test_date }}</p>
                </div>
                
                <!-- 对比概览 -->
                <div class="section">
                    <h2 class="section-title">对比概览</h2>
                    <p>对比任务数量: {{ comparison_data.comparison_count }}</p>
                    <p>最佳性能任务: {{ comparison_data.best_performance_task.task_name }}</p>
                    {% if comparison_data.worst_performance_task %}
                    <p>性能最差任务: {{ comparison_data.worst_performance_task.task_name }}</p>
                    {% endif %}
                </div>
                
                <!-- 性能排名 -->
                <div class="section">
                    <h2 class="section-title">性能排名</h2>
                    
                    <h4>TPS排名</h4>
                    <table class="table">
                        <thead>
                            <tr><th>排名</th><th>任务名称</th><th>平均TPS</th></tr>
                        </thead>
                        <tbody>
                            {% for rank, task in comparison_data.rankings.tps %}
                            <tr>
                                <td>{{ loop.index }}</td>
                                <td>{{ task.task_name }}</td>
                                <td>{{ task.value|round(2) }}</td>
                            </tr>
                            {% endfor %}
                        </tbody>
                    </table>
                    
                    <h4>响应时间排名</h4>
                    <table class="table">
                        <thead>
                            <tr><th>排名</th><th>任务名称</th><th>平均响应时间</th></tr>
                        </thead>
                        <tbody>
                            {% for rank, task in comparison_data.rankings.response_time %}
                            <tr>
                                <td>{{ loop.index }}</td>
                                <td>{{ task.task_name }}</td>
                                <td>{{ task.value|round(2) }} ms</td>
                            </tr>
                            {% endfor %}
                        </tbody>
                    </table>
                </div>
                
                <!-- 对比图表 -->
                {% if charts %}
                <div class="section">
                    <h2 class="section-title">对比图表</h2>
                    {% for chart_name, chart_data in charts.items() %}
                    <div class="chart-container">
                        <h3>{{ chart_configs[chart_name].title if chart_configs and chart_name in chart_configs else chart_name }}</h3>
                        <img src="data:image/png;base64,{{ chart_data }}" alt="{{ chart_name }}" class="chart-image">
                    </div>
                    {% endfor %}
                </div>
                {% endif %}
                
                <!-- 性能差异分析 -->
                {% if comparison_data.performance_differences %}
                <div class="section">
                    <h2 class="section-title">性能差异分析</h2>
                    {% for task_id, diff in comparison_data.performance_differences.items() %}
                    <div class="metric-card">
                        <h4>任务ID: {{ task_id }}</h4>
                        <p>TPS差异: {{ diff.tps_diff_percent|round(2) }}%</p>
                        <p>响应时间差异: {{ diff.rt_diff_percent|round(2) }}%</p>
                        <p>错误率差异: {{ diff.error_diff_percent|round(2) }}%</p>
                    </div>
                    {% endfor %}
                </div>
                {% endif %}
                
                <!-- 建议 -->
                {% if recommendations %}
                <div class="recommendations">
                    <h4>对比分析建议</h4>
                    <ul>
                    {% for recommendation in recommendations %}
                        <li>{{ recommendation }}</li>
                    {% endfor %}
                    </ul>
                </div>
                {% endif %}
                
                <div class="footer">
                    <p>报告生成时间: {{ generation_time }}</p>
                    <p>由 HRUN 性能测试平台自动生成</p>
                </div>
            </div>
        </body>
        </html>
        """
    
    def generate_chart(self, chart_type: str, data: Dict, title: str = "", **kwargs) -> str:
        """生成图表并返回base64编码"""
        try:
            plt.figure(figsize=(10, 6))
            plt.style.use('seaborn-v0_8-whitegrid')
            
            if chart_type == 'line':
                self._generate_line_chart(data, title, **kwargs)
            elif chart_type == 'bar':
                self._generate_bar_chart(data, title, **kwargs)
            elif chart_type == 'pie':
                self._generate_pie_chart(data, title, **kwargs)
            elif chart_type == 'histogram':
                self._generate_histogram_chart(data, title, **kwargs)
            elif chart_type == 'multi_line':
                self._generate_multi_line_chart(data, title, **kwargs)
            elif chart_type == 'bar_comparison':
                self._generate_comparison_bar_chart(data, title, **kwargs)
            else:
                # 默认线性图
                self._generate_line_chart(data, title, **kwargs)
            
            plt.title(title, fontsize=16, fontweight='bold')
            plt.tight_layout()
            
            # 保存到内存并转换为base64
            buffer = io.BytesIO()
            plt.savefig(buffer, format='png', dpi=150, bbox_inches='tight')
            buffer.seek(0)
            chart_base64 = base64.b64encode(buffer.getvalue()).decode()
            buffer.close()
            plt.close()
            
            return chart_base64
            
        except Exception as e:
            print(f"生成图表失败: {e}")
            return ""
    
    def _generate_line_chart(self, data: Dict, title: str, **kwargs):
        """生成线性图"""
        x_data = data.get('x', [])
        y_data = data.get('y', [])
        
        if x_data and y_data:
            plt.plot(x_data, y_data, marker='o', linewidth=2, markersize=4)
            plt.xlabel(data.get('xlabel', 'X轴'))
            plt.ylabel(data.get('ylabel', 'Y轴'))
            plt.xticks(rotation=45)
    
    def _generate_bar_chart(self, data: Dict, title: str, **kwargs):
        """生成柱状图"""
        x_data = data.get('x', [])
        y_data = data.get('y', [])
        
        if x_data and y_data:
            plt.bar(x_data, y_data, alpha=0.7)
            plt.xlabel(data.get('xlabel', 'X轴'))
            plt.ylabel(data.get('ylabel', 'Y轴'))
            plt.xticks(rotation=45)
    
    def _generate_pie_chart(self, data: Dict, title: str, **kwargs):
        """生成饼图"""
        labels = data.get('labels', [])
        values = data.get('values', [])
        
        if labels and values:
            plt.pie(values, labels=labels, autopct='%1.1f%%', startangle=90)
            plt.axis('equal')
    
    def _generate_histogram_chart(self, data: Dict, title: str, **kwargs):
        """生成直方图"""
        values = data.get('values', [])
        
        if values:
            plt.hist(values, bins=kwargs.get('bins', 20), alpha=0.7, edgecolor='black')
            plt.xlabel(data.get('xlabel', '值'))
            plt.ylabel(data.get('ylabel', '频次'))
    
    def _generate_multi_line_chart(self, data: Dict, title: str, **kwargs):
        """生成多线图"""
        x_data = data.get('x', [])
        series = data.get('series', {})
        
        if x_data and series:
            for name, y_data in series.items():
                plt.plot(x_data, y_data, marker='o', label=name, linewidth=2, markersize=4)
            
            plt.xlabel(data.get('xlabel', 'X轴'))
            plt.ylabel(data.get('ylabel', 'Y轴'))
            plt.legend()
            plt.xticks(rotation=45)
    
    def _generate_comparison_bar_chart(self, data: Dict, title: str, **kwargs):
        """生成对比柱状图"""
        categories = data.get('categories', [])
        series = data.get('series', {})
        
        if categories and series:
            x = np.arange(len(categories))
            width = 0.35
            
            series_items = list(series.items())
            for i, (name, values) in enumerate(series_items):
                offset = (i - len(series_items)/2 + 0.5) * width
                plt.bar(x + offset, values, width, label=name, alpha=0.8)
            
            plt.xlabel(data.get('xlabel', '指标'))
            plt.ylabel(data.get('ylabel', '值'))
            plt.xticks(x, categories, rotation=45)
            plt.legend()
    
    def generate_report(self, template_type: str, data: Dict, output_format: str = 'html') -> str:
        """生成报告"""
        try:
            template = self.templates.get(template_type)
            if not template:
                raise ValueError(f"未找到模板类型: {template_type}")
            
            # 准备模板数据
            template_data = self._prepare_template_data(data, template)
            
            # 生成图表
            charts = {}
            if 'chart_data' in data and template.chart_configs:
                for chart_name, chart_config in template.chart_configs.items():
                    if chart_name in data['chart_data']:
                        chart_base64 = self.generate_chart(
                            chart_config['type'],
                            data['chart_data'][chart_name],
                            chart_config['title']
                        )
                        if chart_base64:
                            charts[chart_name] = chart_base64
            
            template_data['charts'] = charts
            template_data['chart_configs'] = template.chart_configs
            template_data['css_styles'] = template.css_styles
            
            # 渲染模板
            jinja_template = Template(template.template_content)
            rendered_html = jinja_template.render(**template_data)
            
            return rendered_html
            
        except Exception as e:
            raise Exception(f"生成报告失败: {e}")
    
    def _prepare_template_data(self, data: Dict, template: ReportTemplate) -> Dict:
        """准备模板数据"""
        template_data = data.copy()
        
        # 添加默认数据
        template_data.setdefault('generation_time', datetime.now().strftime('%Y-%m-%d %H:%M:%S'))
        template_data.setdefault('report_title', f"{template.name}")
        template_data.setdefault('test_date', datetime.now().strftime('%Y-%m-%d'))
        
        return template_data
    
    def add_custom_template(self, template: ReportTemplate):
        """添加自定义模板"""
        self.templates[template.template_type] = template
    
    def list_templates(self) -> List[Dict]:
        """列出所有模板"""
        return [
            {
                'name': template.name,
                'type': template.template_type,
                'description': template.description
            }
            for template in self.templates.values()
        ]


# 全局报告生成器实例
report_generator = PerformanceReportGenerator()


def get_report_generator() -> PerformanceReportGenerator:
    """获取报告生成器实例"""
    return report_generator